home *** CD-ROM | disk | FTP | other *** search
/ T&A 2 the Maxx 3 / T and A 2 The Maxx Number 3.iso / viewers / unixview / xflitar.z / xflitar / read.c < prev    next >
C/C++ Source or Header  |  1991-04-19  |  11KB  |  445 lines

  1. /*
  2.                xflick - Ron Schnell, March, 1991
  3.  
  4.            This code is provided as is, with no warrantees, expressed
  5.                or implied.  I believe this code to be free of encumbrance,
  6.            and offer it to the public domain.  I ask, however, that
  7.            this paragraph and my name be retained in any modified
  8.            versions of the file you may make, and that you notify me
  9.            of any improvements you make to the code.
  10.  
  11.            Ron Schnell (ronnie@sos.com)
  12. */
  13.  
  14. /*
  15.     The following changes are from Michael Pall
  16.     (pall@rz.uni-karlsruhe.de) Mar 25-28 1991:
  17.  
  18.     Lots of bugfixes and changes to the structure of the files.
  19.     The interpretation part is now in this file.
  20. */
  21.  
  22. /*    This is read.c, the functions which read in FLI structures in 
  23.       a machine independent format.  */
  24.  
  25.  
  26. #include <stdio.h>
  27. #include <sys/types.h>
  28. #include <unistd.h>
  29. #include "xflick.h"
  30.  
  31. #define TRUE 1
  32. #define FALSE 0
  33.  
  34. extern int verbose;
  35.  
  36. void
  37. read_flihead(fd, header)
  38. int fd;
  39. struct fli_header *header;
  40. {
  41.     unsigned char *buf = (unsigned char *)malloc(SIZE_HEADER);
  42.     unsigned char *sbf;
  43.     int i;
  44.  
  45.     sbf = buf;
  46.     (void) read(fd, buf, SIZE_HEADER);
  47.     header->fhd_size = get_long(buf);
  48.     buf += LONGSIZE;
  49.  
  50.     header->fhd_magic = get_short(buf);
  51.     buf += SHORTSIZE;
  52.  
  53.     header->fhd_frames = get_short(buf);
  54.     buf += SHORTSIZE;
  55.  
  56.     header->fhd_width = get_short(buf);
  57.     buf += SHORTSIZE;
  58.  
  59.     header->fhd_height = get_short(buf);
  60.     buf += SHORTSIZE;
  61.  
  62.     header->fhd_gap = get_short(buf);
  63.     buf += SHORTSIZE;   /* nothing */
  64.  
  65.     header->fhd_flags = get_short(buf);
  66.     buf += SHORTSIZE;   /* flags */
  67.  
  68.     header->fhd_speed = get_short(buf);
  69.     buf += SHORTSIZE;
  70.  
  71.     header->fhd_next = get_long(buf);
  72.     buf += LONGSIZE;
  73.  
  74.     header->fhd_frit = get_long(buf);
  75.     buf += LONGSIZE;
  76.  
  77.     bcopy(buf, header->fhd_expand, FHD_EXPAND_SIZE);
  78.  
  79.     free(sbf);
  80.  
  81.     if (verbose) {
  82.       fprintf(stderr, "header->fhd_size: %d\n", header->fhd_size);
  83.       fprintf(stderr, "header->fhd_magic: 0x%x\n", header->fhd_magic);
  84.       fprintf(stderr, "header->fhd_frames: %d\n", header->fhd_frames);
  85.       fprintf(stderr, "header->fhd_width: %d\n", header->fhd_width);
  86.       fprintf(stderr, "header->fhd_height: %d\n", header->fhd_height);
  87.       fprintf(stderr, "header->fhd_gap: 0x%x\n", header->fhd_gap);
  88.       fprintf(stderr, "header->fhd_flags: 0x%x\n", header->fhd_flags);
  89.       fprintf(stderr, "header->fhd_speed: %d\n", header->fhd_speed);
  90.       fprintf(stderr, "header->fhd_next: %d\n", header->fhd_next);
  91.       fprintf(stderr, "header->fhd_frit: 0x%x\n", header->fhd_frit);
  92.       fprintf(stderr, "header->fhd_expand: ");
  93.       for (i = 0; i < FHD_EXPAND_SIZE; i++)
  94.     fprintf(stderr, "%x ", 0xff & (unsigned int)header->fhd_expand[i]);
  95.       fprintf(stderr, "\n");
  96.     }
  97. }
  98.  
  99. void
  100. read_fheader(fd, fheader)
  101. int fd;
  102. struct frame_header *fheader;
  103. {
  104.     unsigned char data[SIZE_FHEADER];
  105.     unsigned char *buf = data;
  106.     int ret;
  107.     unsigned char tmp;
  108.     int syncNotFound = TRUE;
  109.     int i;
  110.  
  111.     /* Syncronize to the magic word */
  112.     i = 0;
  113.     do {
  114.       ret = read(fd, &tmp, 1);
  115.       ++i;
  116.       if (verbose)
  117.     fprintf(stderr, "read1 i: %d tmp: 0x%x sync: %d\n",
  118.         i, 0xff & (unsigned int)tmp, syncNotFound);
  119.       if (tmp == (unsigned char)0xfa) {
  120.     ret = read(fd, &tmp, 1);
  121.     ++i;
  122.     if (tmp == (unsigned char)0xf1)
  123.       syncNotFound = FALSE;
  124.     else
  125.       syncNotFound = TRUE;
  126.     if (verbose)
  127.       fprintf(stderr, "read2 i: %d tmp: 0x%x sync: %d\n",
  128.           i, 0xff & (unsigned int)tmp, syncNotFound);
  129.       }
  130.     } while((syncNotFound == TRUE) && (ret > 0));
  131.  
  132.     if (ret < 0) {
  133.       fprintf(stderr,
  134.     "Error reading input file looking for frame header magic number. i: %d\n", i);
  135.       exit(-1);
  136.     }
  137.     
  138.     if (verbose)
  139.       fprintf(stderr, "After Sync i: %d sync: %d ret: %d\n",
  140.           i, syncNotFound, ret);
  141.  
  142.     if ((ret = lseek(fd, -6, SEEK_CUR)) < 0) {
  143.       perror("Seeking to begining of frame");
  144.       exit(-1);
  145.     }
  146.  
  147.     (void) read(fd, buf, SIZE_FHEADER);
  148.  
  149.     fheader->fr_size = get_long(buf);
  150.     buf += LONGSIZE;
  151.     fheader->fr_magic = get_short(buf);
  152.     buf += SHORTSIZE;
  153.     fheader->fr_chunks = get_short(buf);
  154.     bcopy(buf, fheader->fr_expand, FR_EXPAND_SIZE);
  155.  
  156.  
  157.     if (verbose) {
  158.       fprintf(stderr, "fheader->fr_size: %d\n", fheader->fr_size);
  159.       fprintf(stderr, "fheader->fr_magic: 0x%x\n", fheader->fr_magic);
  160.       fprintf(stderr, "fheader->fr_chunks: %d\n", fheader->fr_chunks);
  161.       fprintf(stderr, "fheader->fr_expand: ");
  162.       for (i = 0; i < FR_EXPAND_SIZE; i++)
  163.     fprintf(stderr, "%d ", 0xff & (unsigned int)fheader->fr_expand[i]);
  164.       fprintf(stderr, "\n");
  165.     }
  166.  
  167. }
  168.  
  169. void
  170. read_chunk(fd, chunk)
  171. int fd;
  172. struct chunk_header *chunk;
  173. {
  174.     unsigned char data[SIZE_CHEADER];
  175.     unsigned char *buf = data;
  176.  
  177.     (void) read(fd, buf, SIZE_CHEADER);
  178.     chunk->ch_bytes = get_long(buf);
  179.     buf += LONGSIZE;
  180.     chunk->ch_type = get_short(buf);
  181.  
  182.     if (verbose) {
  183.       fprintf(stderr, "chunk->ch_bytes: %d\n", chunk->ch_bytes);
  184.       fprintf(stderr, "chunk->ch_type: %d\n", chunk->ch_type);
  185.     }
  186. }
  187.  
  188. void
  189. interpret_fli(fd,header,data,notfirst,func)
  190. int fd;            /* The file descriptor */
  191. struct fli_header *header;    /* The header of the file */
  192. unsigned char *data;    /* A pointer to the pixel data */
  193. int notfirst;        /* Is this not the first time through? */
  194. void (*func)();        /* The function that stores or displays the chunks */
  195. {
  196.     int i, j, s, l, k;            /* Random look/status ints */
  197.     short ndiff;        /* To hold the # lines changed from last frame */
  198.     struct frame_header fheader;    /* To hold each frame header */
  199.     struct chunk_header chunk;        /* To hold each chunk header */
  200.     unsigned char *buf=(unsigned char *)0;
  201.                     /* malloc'd space to hold each chunk */
  202.     int bufalloc;            /* Space already allocated for buf */
  203.     int skchange, skcount, sicount;  /* Various pixel/data index's */
  204.     unsigned char *cptr,*dptr,*eptr;     /* data pointers into *buf */
  205.     int npack;                /* Number of packets in this chunk */
  206.     unsigned char by;            /* To hold a byte */
  207.     int curx, cury;            /* The current x & y coords */
  208.     short wwidth, wheight;        /* Width and height of the window */
  209.     int topy,bottomy,leftx,rightx;  /* For optimizing FLI_LC chunks */
  210.  
  211.     static long twopos;            /* To keep the file offset of frame # 2 */
  212.  
  213.     wwidth = header->fhd_width;
  214.     wheight = header->fhd_height;
  215.  
  216.     for (i=0; i <= header->fhd_frames; i++)
  217.     {
  218.  
  219.     /* The following stuff ist only needed if we display the frames
  220.        while we interpret the file */
  221.  
  222.     /* If this is the first time through, we display frame # 1,
  223.        otherwise, we skip right to frame two */
  224.  
  225.     if ((notfirst) && (i==0))
  226.     {
  227.         (void) lseek(fd, twopos, 0);
  228.         continue;
  229.     }
  230.  
  231.     /* If this is the first time through and we are at frame #2,
  232.        save our file offset for the next loop through */
  233.         
  234.     if (!(notfirst) && (i==1))
  235.         twopos = lseek(fd, 0, 1);
  236.         
  237.     /* Each frame has a header */
  238.  
  239.     read_fheader(fd, &fheader);
  240.  
  241.     for (j=0; j < fheader.fr_chunks; j++)
  242.     {
  243.         /* Each chunk also has a header */
  244.         read_chunk(fd, &chunk);
  245.  
  246.         /* Malloc the space to hold whole chunk, unless it
  247.            is a COPY chunk. Malloc/Realloc only if necessary */
  248.  
  249.         if (chunk.ch_type != FLI_COPY) {
  250.         if (!buf)
  251.         {
  252.             buf = (unsigned char *)malloc(chunk.ch_bytes);
  253.             bufalloc = chunk.ch_bytes;
  254.         }
  255.         else
  256.         {
  257.             if (bufalloc < chunk.ch_bytes)
  258.             {
  259.             buf = (unsigned char *)realloc(buf, chunk.ch_bytes);
  260.             bufalloc = chunk.ch_bytes;
  261.             }
  262.         }
  263.           }    
  264.  
  265.         /* A COPY chunk means 64k of uncompressed image data,
  266.            read it directly into the image */
  267.  
  268.         if (chunk.ch_type == FLI_COPY)
  269.         s = read(fd, data, wwidth*wheight);
  270.         else
  271.         s = read(fd, buf, chunk.ch_bytes -  6);
  272.  
  273.         if (s < 0) {
  274.         fprintf(stderr, "s: %d fd: %d data: 0x%x chunk.ch_bytes: %d\n",
  275.             s, fd, data, chunk.ch_bytes);
  276.         xferror("Error reading image data.");
  277.           }
  278.  
  279.         cptr = buf;
  280.  
  281.         switch (chunk.ch_type) {
  282.         case FLI_COPY:
  283.         (*func)(FLI_COPY, i, data, 0,0, 0,0, wwidth,wheight);
  284.         break;
  285.  
  286.         /* A BLACK chunk */
  287.  
  288.         case FLI_BLACK:
  289.         bzero(data, wwidth * wheight);
  290.         (*func)(FLI_BLACK, i, data, 0,0, 0,0, wwidth,wheight);
  291.         break;
  292.  
  293.         /* A COLOR chunk:  A compressed colormap to be stored or
  294.            changed */
  295.  
  296.         case FLI_COLOR:
  297.         npack = get_short(cptr);
  298.         cptr += SHORTSIZE;
  299.  
  300.         for (l=0; l < npack; l++)
  301.         {
  302.             skcount = *(cptr++);     /* # colors not to change */
  303.             skchange = *(cptr++);    /* # of colors to change */
  304.             if (!skchange)           /* (0 means all) */
  305.             skchange=MAXCOL;
  306.         
  307.             /* The colors are stored in the right 6 bits
  308.                of the byte.  We then convert it to a short. */
  309.  
  310.             (*func)(FLI_COLOR, i, cptr, skcount, skchange, 0,0, 0,0);
  311.             cptr += skchange * 3;
  312.         }
  313.         break;
  314.  
  315.  
  316.         /* Line compressed, and bytewise/run-length compressed
  317.            chunks are similar.  BRUN chunks always start at the
  318.            top, while LC chunks can skip lines.  Also, LC chunks
  319.                can skip bytes on each line.  The sign of the
  320.            byte also has opposite meanings for the two! */
  321.  
  322.         case FLI_LC:
  323.         curx = 0;
  324.         cury = get_short(cptr);     /* Lines at top to skip */
  325.         cptr += SHORTSIZE;
  326.         ndiff = get_short(cptr);    /* # of lines different */
  327.         cptr += SHORTSIZE;
  328.  
  329.         topy = cury;
  330.         bottomy = cury + ndiff;
  331.  
  332.             leftx = wwidth;
  333.             rightx = 0;
  334.     
  335.         for (k=0; k < ndiff; k++)    /* Go through each line */
  336.         {
  337.             npack = *(cptr++);       /* # packets this line */
  338.  
  339.             for (l=0; l < npack; l++)
  340.             {
  341.             skcount = *(cptr++);    /* # bytes to skip */
  342.             
  343.             if (l == 0 && skcount < leftx)
  344.                 leftx = skcount;
  345.  
  346.             curx += skcount;
  347.  
  348.             /* The number of bytes in this packet to change */
  349.  
  350.             sicount = *(cptr++);
  351.  
  352.             /* Positive, for LC means bytes the changes follow,
  353.                for BRUN means one byte to follow, spread it
  354.                through. */
  355.  
  356.             if (sicount < 128)
  357.             {
  358.                 bcopy(cptr, data + ((wwidth * cury) + curx),
  359.                   sicount);
  360.                 cptr += sicount;
  361.                 curx += sicount;
  362.             }
  363.  
  364.             else
  365.  
  366.             /* Negative, the opposite */
  367.  
  368.             {
  369.                 sicount = 256 - sicount;
  370.                 by = *(cptr++);
  371.                 dptr = data + wwidth * cury + curx;
  372.                 eptr = dptr + sicount;
  373.                 do
  374.                 *(dptr++) = by;
  375.                 while (dptr < eptr);
  376.                 curx += sicount;
  377.             }
  378.             }
  379.  
  380.             if (curx > rightx)
  381.             rightx = curx;
  382.  
  383.             /* Next line */
  384.             cury++;
  385.             curx = 0;
  386.         }
  387.         
  388.         (*func)(FLI_LC, i, data, leftx,topy, leftx,topy,
  389.             rightx-leftx,bottomy-topy);
  390.         break;
  391.  
  392.         case FLI_BRUN:
  393.         dptr = data;
  394.     
  395.         for (k=0; k < wheight; k++)    /* Go through each line */
  396.         {
  397.             npack = *(cptr++);       /* # packets this line */
  398.  
  399.             for (l=0; l < npack; l++)
  400.             {
  401.             /* The number of bytes in this packet to change */
  402.  
  403.             sicount = *(cptr++);
  404.  
  405.             /* Positive, for LC means bytes the changes follow,
  406.                for BRUN means one byte to follow, spread it
  407.                through. */
  408.  
  409.             if (sicount < 128)
  410.             {
  411.                 by = *cptr++;
  412.                 eptr = dptr + sicount;
  413.                 while (dptr < eptr)
  414.                 *(dptr++) = by;
  415.             }
  416.  
  417.             /* Negative, the opposite */
  418.  
  419.             else
  420.  
  421.             {
  422.                 sicount = 256 - sicount;
  423.                 bcopy(cptr, dptr, sicount);
  424.                 cptr += sicount;
  425.                 dptr += sicount;
  426.             }
  427.             }
  428.         }
  429.  
  430.         (*func)(FLI_BRUN, i, data, 0,0, 0,0, wwidth,wheight);
  431.         break;
  432.         }
  433.  
  434.     }
  435.     
  436.     /* Send a FLI_SYNC after each frame to get accurate timing */
  437.     (*func)(FLI_SYNC, i, (unsigned char *)0, 0,0, 0,0, 0,0);
  438.     }
  439.  
  440.     /* Only free the buffer if we allocated something */
  441.     if (!buf)
  442.     free(buf);
  443.  
  444. }
  445.